package pod

import (
	"errors"
	"fmt"
	"path"
	"path/filepath"
	"publish/shell"
	"strings"
)

type Repo struct {
	Name   string
	Type   string
	URL    string
	Path   string
	Action string
}

func init() {

}

func RepoList() ([]*Repo, error) {
	success, result := shell.Exec("pod repo")
	if success {
		list := strings.Split(result, "\n")
		count := int(len(list) / 5)
		if list[0] == "" {
			list = list[1 : count*5+1]
		}
		repoList := [][]string{}
		for i := 0; i < count; i++ {
			repoList = append(repoList, list[i*5:(i+1)*5])
		}

		var repos = []*Repo{}
		for _, v := range repoList {
			if repo, err := extractRepo(v); err == nil {
				repos = append(repos, repo)
			}
		}
		return repos, nil
	}
	return nil, errors.New(result)
}

/**
1. 检测本地项目状态：是否需要暂存、拉取
2. 同步远端代码到本地
3. 同步远端tag到本地
*/
func SyncProject(path string) error {
	//TODO: need merge after pull

	// check sataus
	success, result := shell.ExecOnDir("git status", path)
	if !success {
		return errors.New(result)
	}
	if !strings.Contains(result, "nothing to commit") || strings.Contains(result, "use \"git pull\" ") {
		return fmt.Errorf("%s : please sync remote branch or stash your change", path)
	}

	// sync code
	success, result = shell.ExecOnDir("git pull", path)
	if !success {
		return fmt.Errorf("%s : git pull err \n   %s", path, result)
	}

	// sync tags
	success, result = shell.ExecOnDir("git pull --tags", path)
	if !success {
		return fmt.Errorf("%s : sync remote tags err \n   %s", path, result)
	}
	return nil
}

func (repo *Repo) PushChanges() error {
	success, result := shell.ExecOnDir("git push", repo.Path)
	if !success {
		return errors.New(result)
	}
	return nil
}

func extractRepo(info []string) (*Repo, error) {
	repo := &Repo{}
	for i, v := range info {
		switch i {
		case 0:
			repo.Name = strings.Trim(v, " ")
		case 1:
			repo.Type = strings.Trim(strings.Split(v, "- Type:")[1], " ")
		case 2:
			repo.URL = strings.Trim(strings.Split(v, "- URL:")[1], " ")
		case 3:
			repo.Path = strings.Trim(strings.Split(v, "- Path:")[1], " ")
		}
	}
	return repo, nil
}

func (repo *Repo) AddSpec(spec *SpecInfo) error {
	// find module folder
	folder := path.Join(repo.Path, spec.Name)
	match, err := filepath.Glob(folder)
	if err != nil {
		return err
	}
	switch len(match) {
	case 0:
		//create
		repo.Action = "Add"
		success, result := shell.ExecOnDir("mkdir "+spec.Name, repo.Path)
		if !success {
			return errors.New(result)
		}
	case 1:
		//check version folder
		repo.Action = "Update"
	default:
		return errors.New("copy local podspec to repo err : local repo illegal")
	}

	// find module version folder
	vFolder := path.Join(folder, spec.Version)
	match, err = filepath.Glob(vFolder)
	if err != nil {
		return err
	}
	switch len(match) {
	case 0:
		//create and cp
		success, result := shell.ExecOnDir("mkdir "+spec.Version, folder)
		if !success {
			return errors.New(result)
		}
		success, result = shell.Exec("cp " + spec.Name + ".podspec " + vFolder)
		if !success {
			return errors.New(result)
		}
	default:
		return errors.New("copy local podspec to repo err : this version folder is exist")
	}

	return nil
}

func (repo *Repo) Update(spec *SpecInfo) error {
	success, result := shell.ExecOnDir("git add .", repo.Path)
	if !success {
		return errors.New("git add . err : " + result)
	}
	success, result = shell.ExecOnDirWithOption(fmt.Sprintf("git commit -m '[%s] %s (%s)'", repo.Action, spec.Name, spec.Version), repo.Path)
	if !success {
		return errors.New("git commit err : " + result)
	}
	return nil
}
